from math import pi
import numpy as np
import cmath
from numpy.core.fromnumeric import shape
import PIL.Image as Image

class FourierTransform():

    def __init__(self):
        pass

    def __call__(self, image, **kwds):
        return self.call(image)

    def computeF(self, tmp, inputs):
        SUM = 0.0 + 0.0j
        for i in range(len(tmp)):
            for j in range(len(tmp[0])):
                SUM += tmp[i][j] * inputs[i][j]
        return SUM / (inputs.shape[0] * inputs.shape[1])

    def call(self, image):
        inputs = np.array(image)
        B = {}
        h = len(inputs)
        w = len(inputs[0])
        tmpList = [[0.0 + 0.0j for i in range(w)] for j in range(h)]
        F = np.array(tmpList)
        Fabs = np.zeros(shape = (h, w))
        e = np.array(tmpList)
        centerh = h // 2
        centerw = w // 2
        for i in range(-centerh, h - centerh):
            for j in range(-centerw, w - centerw):
                tmp = np.array(tmpList)
                tmp2 = np.array(tmpList)
                for m in range(-centerh, h - centerh):
                    for n in range(-centerw, w - centerw):
                        tmp[m + centerh][n + centerw] = np.exp((2 * pi * i * m / h + 2 * pi * j * n / w) * 1j)
                        tmp2[m + centerh][n + centerw] = np.exp( - (2 * pi * i * m / h + 2 * pi * j * n / w) * 1j)
                B[str(i) + "," + str(j)] = tmp
                Ftmp = self.computeF(tmp2, inputs)
                F[i + centerh][j + centerw] = Ftmp
                Fabs[i + centerh][j + centerw] = abs(Ftmp)
                e[i + centerh][j + centerw] = Ftmp / abs(Ftmp)
            print(i)
        return B, F, Fabs, e

def reconstructImage(imageL_arr, F, B):
    h = len(imageL_arr)
    w = len(imageL_arr[0])
    tmpList = [[0.0 + 0.0j for i in range(w)] for j in range(h)]
    recon = np.array(tmpList)
    for i in range(h):
        for j in range(w):
            i_ = i - h // 2
            j_ = j - w // 2
            recon = recon + F[i][j] * B[str(i_) + "," + str(j_)]
    reconImage = Image.fromarray(recon.astype("uint")).convert("L")
    reconImage.save("./FT/reconImage.jpg")


imageRGB = Image.open("1.jpg")
imageL = imageRGB.convert("L")
imageL_arr = np.array(imageL)
print(imageL_arr.shape)
Ffffff = FourierTransform()
B, F, Fabs, e = Ffffff(imageL_arr)
num = 0
for key, value in B.items():
    if num > 10:
        break
    rel = np.real(value) * 255
    img = Image.fromarray(rel.astype("uint")).convert("L")
    num += 1
    name = "./FT/" + "B_" + key + ".jpg"
    img.save(name)

FabsImage = Image.fromarray(Fabs.astype("uint")).convert("L")
FabsImage.save("./FT/FabsImage.jpg")
ee = np.real(e) * 255
eImage = Image.fromarray(ee.astype("uint")).convert("L")
eImage.save("./FT/eRealImage.jpg")

reconstructImage(imageL_arr, F, B)
